import { schema } from '@/ts/base';
import { IBelong } from '@/utils/excel';

interface RuleCondition {
  field: string;
  operator: string;
  value: any;
}

interface Rule {
  ruleId: string;
  ruleName: string;
  description: string;
  mandatory: boolean;
  conditions: (RuleCondition | 'and' | 'or')[];
}

// 校验规则接口
interface ValidationRule {
  ruleId: string;
  ruleName: string;
  description: string;
  mandatory: boolean;
  conditions: any[]; // 验证条件列表
}

// 验证操作符类型
export type Operator =
  | '='
  | '<>'
  | '<'
  | '<='
  | '>'
  | '>='
  | 'contains'
  | 'endswith'
  | 'isblank'
  | 'isnotblank'
  | 'notcontains'
  | 'startswith'
  | 'between';

// 订单校验类
export class OrderValidator {
  errors: string[] = [];
  space: IBelong;
  rules: Rule[];
  constructor(space: IBelong) {
    this.space = space;
    this.rules = [];
    this._initOrderValidator();
  }

  async _initOrderValidator() {
    this.rules = await this.generateValidationRules();
  }

  /**
   * 验证订单
   * @param order - 要验证的订单对象
   * @returns 验证错误信息数组
   */
  public validateOrder(order: schema.XOrder): string[] {
    const errors: string[] = [];
    for (const rule of this.rules) {
      const isValid = this.evaluateConditions(order, rule.conditions, rule.ruleId);
      if (!isValid) {
        errors.push(`${rule.ruleName}: ${rule.description}`);
      }
    }
    return errors;
  }

  /**
   * 验证条件
   * @param obj - 要验证的对象
   * @param conditions - 条件数组
   * @returns 是否满足所有条件
   */
  private evaluateConditions(
    obj: any,
    conditions: (RuleCondition | 'and' | 'or')[],
    ruleId: string, // 传入规则 ID
  ): boolean {
    let result: boolean | null = null;
    let currentOp: 'and' | 'or' | null = null;
    if (['ORDER_BASIC_007'].includes(ruleId)) {
      // 校验第一个条件（如果第一个条件不成立，直接返回 true）
      const firstCondition = conditions[0];
      if (typeof firstCondition !== 'string') {
        const firstFieldValue = this.getFieldValue(obj, firstCondition.field);
        const firstResult = this.evaluateCondition(
          firstFieldValue,
          firstCondition.operator,
          firstCondition.value,
        );
        if (!firstResult) {
          // 第一个条件不满足，直接返回 true（校验通过）
          return true;
        }
      }
    }

    for (const condition of conditions) {
      if (typeof condition === 'string') {
        currentOp = condition;
      } else {
        let fieldValue = this.getFieldValue(obj, condition.field);
        let conditionResult = false;
        if (Array.isArray(fieldValue)) {
          // 如果字段数组为空，表示字段缺失，直接返回 false
          fieldValue = fieldValue.filter((item) => item !== undefined);
          if (fieldValue.length === 0) {
            conditionResult = false;
          } else {
            conditionResult = fieldValue.every((item: any) =>
              this.evaluateCondition(item, condition.operator, condition.value),
            );
          }
        } else {
          conditionResult = this.evaluateCondition(
            fieldValue,
            condition.operator,
            condition.value,
          );
        }
        if (result === null) {
          result = conditionResult;
        } else if (currentOp === 'and') {
          result = result && conditionResult;
        } else if (currentOp === 'or') {
          result = result || conditionResult;
        }
      }
    }
    return result ?? true;
  }

  /**
   * 校验单个条件
   * @param fieldValue - 字段值
   * @param operator - 操作符
   * @param value - 比较值
   * @returns 条件是否满足
   */

  private evaluateCondition(fieldValue: any, operator: string, value: any): boolean {
    switch (operator) {
      case '<>':
        return fieldValue !== value;
      case '=':
        return fieldValue === value;
      case 'in':
        return Array.isArray(value) && value.some((v: any) => v.id === fieldValue);;
      case 'isnotblank':
        return fieldValue !== undefined && fieldValue !== null && fieldValue !== '';
      default:
        return false;
    }
  }

  /**
   * 获取对象字段值
   * 支持点号分隔的深层字段访问和数组字段
   * @param obj - 要获取值的对象
   * @param field - 字段路径
   * @returns 字段值
   */

  private getFieldValue(obj: any, field: string): any | any[] | undefined {
    const fields = field.split('.');
    let value = obj;
    for (const f of fields) {
      if (f.includes('[]')) {
        const key = f.replace('[]', '');
        if (Array.isArray(value[key])) {
          // 递归处理嵌套字段，返回数组
          return value[key].map((item) =>
            this.getFieldValue(item, fields.slice(fields.indexOf(f) + 1).join('.')),
          );
        } else {
          return []; // 数组字段缺失时，返回空数组
        }
      } else {
        if (value && Object.prototype.hasOwnProperty.call(value, f)) {
          value = value[f];
        } else {
          return undefined; // 字段缺失时返回 undefined
        }
      }
    }
    return value;
  }

  /**
   * 生成验证规则
   * 定义所有订单相关的验证规则
   * @returns 验证规则数组
   */
  public async generateValidationRules(): Promise<ValidationRule[]> {
    await this.space.loadMembers(true);
    return [
      {
        ruleId: 'ORDER_BASIC_001',
        ruleName: '订单ID校验',
        description: '订单ID不能为空',
        mandatory: true,
        conditions: [
          {
            field: 'orderNumber',
            operator: '<>',
            value: '',
          },
          'and',
          {
            field: 'orderNumber',
            operator: '<>',
            value: null,
          },
        ],
      },
      {
        ruleId: 'ORDER_BASIC_002',
        ruleName: '商品ID校验',
        description: '商品ID不能为空',
        mandatory: true,
        conditions: [
          {
            field: 'itemList[].id',
            operator: '<>',
            value: '',
          },
          'and',
          {
            field: 'itemList[].id',
            operator: '<>',
            value: null,
          },
        ],
      },
      {
        ruleId: 'ORDER_BASIC_003',
        ruleName: '商品价格校验',
        description: '商品价格不能为空',
        mandatory: true,
        conditions: [
          {
            field: 'itemList[].price',
            operator: '<>',
            value: '',
          },
          'and',
          {
            field: 'itemList[].price',
            operator: '<>',
            value: null,
          },
        ],
      },
      {
        ruleId: 'ORDER_BASIC_004',
        ruleName: '订单实付价校验',
        description: '订单实付价不能为空',
        mandatory: true,
        conditions: [
          {
            field: 'actualPaidPrice',
            operator: '<>',
            value: '',
          },
          'and',
          {
            field: 'actualPaidPrice',
            operator: '<>',
            value: null,
          },
        ],
      },
      {
        ruleId: 'ORDER_BASIC_005',
        ruleName: '订单总金额校验',
        description: '订单总金额不能为空',
        mandatory: true,
        conditions: [
          {
            field: 'totalPrice',
            operator: '<>',
            value: '',
          },
          'and',
          {
            field: 'totalPrice',
            operator: '<>',
            value: null,
          },
        ],
      },
      {
        ruleId: 'ORDER_BASIC_006',
        ruleName: '商品归属校验',
        description: '商品的归属单位不能为空，且有效',
        mandatory: true,
        conditions: [
          {
            field: 'itemList[].belongId',
            operator: '<>',
            value: '',
          },
          'and',
          {
            field: 'itemList[].belongId',
            operator: '<>',
            value: null,
          },
        ],
      },
      {
        ruleId: 'ORDER_BASIC_007',
        ruleName: '下单人校验',
        description: '如果下单单位是本单位，则下单人ID必须属于本单位且有效',
        mandatory: true,
        conditions: [
          {
            field: 'buyer',
            operator: '=',
            value: this.space.id,
          },
          'and',
          {
            field: 'buyerUserId',
            operator: '<>',
            value: '',
          },
          'and',
          {
            field: 'buyerUserId',
            operator: '<>',
            value: null,
          },
          'and',
          {
            field: 'buyerUserId',
            operator: 'in',
            value: this.space.members,
          },
        ],
      }
    ];
  }
}
